﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using WickedFlame.Core;
using WickedFlame.Util.Events;
using WickedFlame.Core.Tools;
using System.Windows.Media;
using WickedFlame.Core.History;
using WickedFlame.Core.Shapes;
using System.Collections.ObjectModel;

namespace WickedFlame.Util
{
    public delegate void ZoomChangedEventHandler(object sender, ZoomChangedEventArgs e);

	[TemplatePart(Name = "PART_SelectedContentHost", Type = typeof(ContentPresenter))]
	public class CanvasManager : System.Windows.Controls.Primitives.Selector
	{
		public event ZoomChangedEventHandler ZoomChanged;
		public event EventHandler CanvasChanged;
		//public event CloseCanvasEventHandler CloseCanvas;

		static CanvasManager()
		{
			DefaultStyleKeyProperty.OverrideMetadata(typeof(CanvasManager), new FrameworkPropertyMetadata(typeof(CanvasManager)));
		}

		public CanvasManager()
		{
			ShapePropertySettings.Settings.FillChanged += new ToolColorChangedDelegate(SetFillBrush);
			ShapePropertySettings.Settings.StrokeChanged += new ToolColorChangedDelegate(SetBorderBrush);
			ShapePropertySettings.Settings.FontFamilyChanged += new FontFamilyChangedDelegate(SetFont);
			ShapePropertySettings.Settings.FontSizeChanged += new FontSizeChangedDelegate(SetFontSize);
			ShapePropertySettings.Settings.StrokeThicknessChanged += new StrokeThicknessChanged(StrokeThicknessChanged);
		}

        public void Dispose()
        {
            var canvas = SelectedItem as DrawingCanvas;
            if (canvas == null)
                return;

            VectorImage img = null;
            foreach (var tmp in VectorImages)
            {
                if (tmp.DrawingCanvas == canvas)
                {
                    img = tmp;
                    break;
                }
            }
            if (img == null)
                return;

            canvas.Dispose();
            this.Items.Remove(canvas);
            VectorImages.Remove(img);
            
            canvas = null;

            if (this.VectorImages.Count > 0)
                SelectedImage = this.VectorImages[this.VectorImages.Count - 1];

        }

		public override void OnApplyTemplate()
		{
			base.OnApplyTemplate();

			if (this.Items.Count > 0)
				this.SelectedIndex = 0;
		}

		#region Members

        public void Add(double width, double height, bool addLayer = true)
        {
            this.Height = height;
            this.Width = width;

            var img = new VectorImage
            {
                //FileName = "Default.vec",
                DrawingCanvas = new DrawingCanvas
            {
                Width = width,
                Height = height,
                HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
                VerticalAlignment = System.Windows.VerticalAlignment.Center

            }
            };

            if (addLayer)
                img.DrawingCanvas.AddLayer();

            VectorImages.Add(img);
            this.Items.Add(img.DrawingCanvas);

            SelectedImage = img;
        }

        public void Add(VectorImage image)
        {
            // remove canvas if it is not written
            var ec = SelectedItem as DrawingCanvas;
            if (ec != null)
                if (ec != null &&
                ec.Layers.Count == 1 &&
                ec.SelectedLayer.ShapeList.Count == 0)
                    Remove(ec);

            VectorImages.Add(image);
            this.Items.Add(image.DrawingCanvas);

            this.Height = image.DrawingCanvas.Height;
            this.Width = image.DrawingCanvas.Width;

            SelectedImage = image;
        }

		public void Add(DrawingCanvas canvas)
		{
			// remove canvas if it is not written
			var ec = SelectedItem as DrawingCanvas;
			if (ec != null)
				if (ec != null &&
				ec.Layers.Count == 1 &&
				ec.SelectedLayer.ShapeList.Count == 0)
					Remove(ec);

            var img = new VectorImage
            {
                DrawingCanvas = canvas
            };
            VectorImages.Add(img);
            this.Items.Add(img.DrawingCanvas);

            this.Height = img.DrawingCanvas.Height;
            this.Width = img.DrawingCanvas.Width;

            SelectedImage = img;
            //SelectedItem = canvas;
		}


		//public void SelectCanvas(DrawingCanvas canvas)
		//{
		//    foreach (var img in VectorImages)
		//    {
		//        if (img.DrawingCanvas == canvas)
		//        {
		//            SelectedImage = img;
		//        }
		//    }
		//    //if (this.Items.Contains(canvas))
		//    //    SelectedItem = canvas;
		//}

		protected override void OnSelectionChanged(SelectionChangedEventArgs e)
		{
			base.OnSelectionChanged(e);

            SelectedContent = SelectedItem;

			var canvas = SelectedItem as DrawingCanvas;
			if (canvas != null)
			{
				canvas.Initialize();
				if (CanvasChanged != null)
					CanvasChanged(this, new EventArgs());

				//TODO:
				//keep scale saved in the drawingcanvas!!!
				this.Height = canvas.Height;
				this.Width = canvas.Width;
			}
		}

        public void Remove(DrawingCanvas canvas)
        {
            if (this.Items.Contains(canvas))
                this.Items.Remove(canvas);

            foreach (var img in VectorImages)
            {
                if (img.DrawingCanvas == canvas)
                {
                    VectorImages.Remove(img);
                    break;
                }
            }

            if (this.VectorImages.Count > 0)
            {
                SelectedImage = VectorImages[VectorImages.Count - 1];
                var c = SelectedItem as DrawingCanvas;
                if (c != null)
                {
                    this.Height = c.Height;
                    this.Width = c.Width;
                }
            }
            else
            {
                //SelectedItem = null;
                this.Height = 0.0;
                this.Width = 0.0;
            }

			//if (CloseCanvas != null)
			//    CloseCanvas(this, new CloseCanvasEventArgs(canvas));
        }

		public void Remove(VectorImage image)
		{
			if (this.Items.Contains(image.DrawingCanvas))
				this.Items.Remove(image.DrawingCanvas);
			
			VectorImages.Remove(image);

			if (this.VectorImages.Count > 0)
			{
				SelectedImage = VectorImages[VectorImages.Count - 1];
				var c = SelectedItem as DrawingCanvas;
				if (c != null)
				{
					this.Height = c.Height;
					this.Width = c.Width;
				}
			}
			else
			{
				SelectedItem = null;
				this.Height = 0.0;
				this.Width = 0.0;
			}

			//if (CloseCanvas != null)
			//    CloseCanvas(this, new CloseCanvasEventArgs(image.DrawingCanvas));
		}

		public void ResizeCanvas(double width, double height)
		{
            width = Math.Round(width);
            height = Math.Round(height);

			var canvas = SelectedItem as DrawingCanvas;
			if (canvas != null)
			{
				canvas.Zoom = 100;
				canvas.Width = width;
				canvas.Height = height;
			}

			this.Width = width;
			this.Height = height;
		}

		/// <summary>
		/// scales the content out (smaller)
		/// </summary>
		/// <param name="percent">percentage to scale out</param>
		public void ZoomOut(int percent)
		{
			var canvas = SelectedItem as DrawingCanvas;
			if (canvas != null)
			{
				if (canvas.Zoom - percent > 0)
					canvas.Zoom -= percent;
				this.Height = (canvas.Height / 100) * canvas.Zoom;
				this.Width = (canvas.Width / 100) * canvas.Zoom;

				//redraw the trackers with the corect scale
				DrawingCanvas.DrawTrackers();

				if (ZoomChanged != null)
					ZoomChanged(this, new ZoomChangedEventArgs(canvas.Zoom));
			}
		}

		/// <summary>
		/// scales the content in (bigger)
		/// </summary>
		/// <param name="percent">percentage to scale in</param>
		public void ZoomIn(int percent)
		{
			var canvas = SelectedItem as DrawingCanvas;
			if (canvas != null)
			{
				canvas.Zoom += percent;
				this.Height = (canvas.Height / 100) * canvas.Zoom;
				this.Width = (canvas.Width / 100) * canvas.Zoom;

				//redraw the trackers with the corect scale
				DrawingCanvas.DrawTrackers();

				if (ZoomChanged != null)
					ZoomChanged(this, new ZoomChangedEventArgs(canvas.Zoom));
			}
		}

		#endregion

		#region DependencieProperties

		//protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
		//{
		//    base.OnPropertyChanged(e);
		//    DependencyProperty prop = e.Property;
		//    if (prop == CanvasManager.SelectedImageProperty)
		//    {
		//        SelectedImage = e.NewValue as VectorImage;
		//        if (SelectedImage != null)
		//            SelectedItem = SelectedImage.DrawingCanvas;
		//        else
		//            SelectedItem = null;
		//    }
		//}

        public VectorImage SelectedImage
        {
            get
            {
                return (VectorImage)GetValue(SelectedImageProperty);
            }
            set
            {
                SetValue(SelectedImageProperty, value);
            }
        }

		public static readonly DependencyProperty SelectedImageProperty =
			DependencyProperty.Register("SelectedImage", typeof(VectorImage), typeof(CanvasManager),
			new FrameworkPropertyMetadata(null, new PropertyChangedCallback(SelectedImagePropertyChanged)));

		private static void SelectedImagePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
		{
			var dt = sender as CanvasManager;
			if (dt == null)
				return;

			dt.SelectedImagChanged(args.NewValue as VectorImage);
		}

		private void SelectedImagChanged(VectorImage newimage)
		{
			SelectedItem = newimage != null ? newimage.DrawingCanvas : null;
		}

		public DrawingCanvas SelectedCanvas
		{
			get
			{
				return this.SelectedItem as DrawingCanvas;
			}
			set
			{
				// get the image that the canvas is contained in and set it to the selectedimage property
				// the selected item will be set in the SelectedImage handler
                foreach (var img in VectorImages)
                {
                    if (img.DrawingCanvas == value)
                        SelectedImage = img;
                }
			}
		}

        public object SelectedContent
        {
            get
            {
                return base.GetValue(SelectedContentProperty);
            }
            internal set
            {
                base.SetValue(SelectedContentPropertyKey, value);
            }
        }
        private static readonly DependencyPropertyKey SelectedContentPropertyKey = DependencyProperty.RegisterReadOnly("SelectedContent", typeof(object), typeof(CanvasManager), new FrameworkPropertyMetadata(null));
        public static readonly DependencyProperty SelectedContentProperty = SelectedContentPropertyKey.DependencyProperty;
        private const string SelectedContentHostTemplateName = "PART_SelectedContentHost";



        public ObservableCollection<VectorImage> VectorImages
        {
            get
            {
                return (ObservableCollection<VectorImage>)GetValue(VectorImagesProperty);
            }
            set
            {
                SetValue(VectorImagesProperty, value);
            }
        }

		//public static readonly DependencyProperty VectorImagesProperty =
		//    DependencyProperty.Register("VectorImages", typeof(ObservableCollection<VectorImage>), typeof(CanvasManager),
		//    new FrameworkPropertyMetadata(new ObservableCollection<VectorImage>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
		//    new PropertyChangedCallback(OnSelectedValueChanged)));
		public static readonly DependencyProperty VectorImagesProperty =
			DependencyProperty.Register("VectorImages", typeof(ObservableCollection<VectorImage>), typeof(CanvasManager),
			new FrameworkPropertyMetadata(new ObservableCollection<VectorImage>()));

		//private static void OnSelectedValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		//{
		//}

		#endregion

		#region Shape Properties Contoler

		void SetFillBrush(Brush brush)
		{
			if (SelectedCanvas == null)
				return;

			var changeCmd = new PropertyChangedCommand(SelectedCanvas.SelectedLayer.ShapeList, SelectedCanvas.SelectedLayerIndex);

			// change all selected objects
			bool change = false;
			foreach (VectorShape shape in SelectedCanvas.SelectedLayer.ShapeList.Selection)
			{
				shape.Fill = ShapePropertySettings.Settings.Fill;
				change = true;
			}

			// add changeCommand to history of changes
			if (change)
			{
				changeCmd.SetNewState();
				SelectedCanvas.PushHistoryCommand(changeCmd);
			}
		}

		void SetBorderBrush(Brush brush)
		{
			if (SelectedCanvas == null)
				return;

			var changeCmd = new PropertyChangedCommand(SelectedCanvas.SelectedLayer.ShapeList, SelectedCanvas.SelectedLayerIndex);

			// change all selected objects
			bool change = false;
			foreach (VectorShape shape in SelectedCanvas.SelectedLayer.ShapeList.Selection)
			{
				shape.Stroke = ShapePropertySettings.Settings.Stroke;
				change = true;
			}

			// add changeCommand to history of changes
			if (change)
			{
				changeCmd.SetNewState();
				SelectedCanvas.PushHistoryCommand(changeCmd);
			}
		}

		void SetFont(FontFamily font)
		{
			if (SelectedCanvas == null)
				return;

			var changeCmd = new PropertyChangedCommand(SelectedCanvas.SelectedLayer.ShapeList, SelectedCanvas.SelectedLayerIndex);

			// change all selected objects
			bool change = false;
			foreach (VectorShape shape in SelectedCanvas.SelectedLayer.ShapeList.Selection)
			{
				TextShape s = shape as TextShape;
				if (s != null)
				{
					s.FontFamily = font;
					change = true;
				}
			}

			// add changeCommand to history of changes
			if (change)
			{
				changeCmd.SetNewState();
				SelectedCanvas.PushHistoryCommand(changeCmd);
			}

			DrawingCanvas.DrawTrackers();
		}

		void SetFontSize(double fontSize)
		{
			if (SelectedCanvas == null)
				return;

			var changeCmd = new PropertyChangedCommand(SelectedCanvas.SelectedLayer.ShapeList, SelectedCanvas.SelectedLayerIndex);

			// change all selected objects
			bool change = false;
			foreach (VectorShape shape in SelectedCanvas.SelectedLayer.ShapeList.Selection)
			{
				TextShape s = shape as TextShape;
				if (s != null)
				{
					s.FontSize = fontSize;
					change = true;
				}
			}

			// add changeCommand to history of changes
			if (change)
			{
				changeCmd.SetNewState();
				SelectedCanvas.PushHistoryCommand(changeCmd);
			}

			DrawingCanvas.DrawTrackers();
		}

		void StrokeThicknessChanged(double stroke)
		{
			if (SelectedCanvas == null)
				return;

			var changeCmd = new PropertyChangedCommand(SelectedCanvas.SelectedLayer.ShapeList, SelectedCanvas.SelectedLayerIndex);

			// change all selected objects
			bool change = false;
			foreach (VectorShape shape in SelectedCanvas.SelectedLayer.ShapeList.Selection)
			{
				shape.StrokeThickness = ShapePropertySettings.Settings.StrokeThickness;
				change = true;
			}

			// add changeCommand to history of changes
			if (change)
			{
				changeCmd.SetNewState();
				SelectedCanvas.PushHistoryCommand(changeCmd);
			}
		}

		#endregion

	}
}
